//
//  CJSkin+Exten.swift
//  CJPack
//
//  Created by 陈警卫 on 2023-04-14.
//

import UIKit
import Foundation

public class CJSkinDeiniter {
    
    var didSkinDeinit: (() -> ())?
    
    init(didSkinDeinit: (() -> Void)? = nil) {
        self.didSkinDeinit = didSkinDeinit
    }
    
    deinit {
        if let didSkinDeinit = didSkinDeinit {
            didSkinDeinit()
            self.didSkinDeinit = nil
        }
    }
}

public extension UIView {
    
    private struct CJSkinViewKey {
        static var cj_textColorkey: Void?
        static var cj_backroundColorkey: Void?
        static var cj_tintColorkey: Void?
        
        static var cj_didSkin: Void?
        static var cj_skinDeiniter: Void?
        static var cj_skinDeiniterBlocks: Void?
    }
    
    /// textColorkey
    var cj_textColorkey: String? {
        get {
            return objc_getAssociatedObject(self, &CJSkinViewKey.cj_textColorkey) as? String
        }
        set {
            objc_setAssociatedObject(self, &CJSkinViewKey.cj_textColorkey, newValue, .OBJC_ASSOCIATION_RETAIN)
            cj_addSkinNotiDeiniter()
        }
    }
    
    /// backroundColorkey
    var cj_backroundColorkey: String? {
        get {
            return objc_getAssociatedObject(self, &CJSkinViewKey.cj_backroundColorkey) as? String
        }
        set {
            objc_setAssociatedObject(self, &CJSkinViewKey.cj_backroundColorkey, newValue, .OBJC_ASSOCIATION_RETAIN)
            cj_addSkinNotiDeiniter()
        }
    }
    
    /// tintColorkey
    var cj_tintColorkey: String? {
        get {
            return objc_getAssociatedObject(self, &CJSkinViewKey.cj_tintColorkey) as? String
        }
        set {
            objc_setAssociatedObject(self, &CJSkinViewKey.cj_tintColorkey, newValue, .OBJC_ASSOCIATION_RETAIN)
            cj_addSkinNotiDeiniter()
        }
    }
    
    /// 全局项目刷新回调(父子类冲突)
    var cj_didSkin: ((Any) -> ())? {
        get {
            return objc_getAssociatedObject(self, &CJSkinViewKey.cj_didSkin) as? ((Any) -> ())
        }
        set {
            objc_setAssociatedObject(self, &CJSkinViewKey.cj_didSkin, newValue, .OBJC_ASSOCIATION_COPY)
            cj_addSkinNotiDeiniter()
        }
    }
    
    
    private func cj_addSkinNotiDeiniter() {
        NotificationCenter.default.removeObserver(self, name: .init(kCJSkinNotiKey), object: nil)
        if objc_getAssociatedObject(self, &CJSkinViewKey.cj_skinDeiniter) == nil {
            let er = cj_addSkinDeiniterBlock { [weak self] in
                if let wself = self {
                    NotificationCenter.default.removeObserver(wself)
                }
            }
            objc_setAssociatedObject(self, &CJSkinViewKey.cj_skinDeiniter, er, .OBJC_ASSOCIATION_RETAIN)
        }
        cj_skinChange()
        NotificationCenter.default.addObserver(self, selector: #selector(cj_skinChange), name: .init(kCJSkinNotiKey), object: nil)
    }
    
    /// CJSkinDeiniter 处理
    private func cj_addSkinDeiniterBlock(block:(() -> ())?) -> CJSkinDeiniter? {
        
        guard let block = block else { return nil }
        
        var blocks = objc_getAssociatedObject(self, &CJSkinViewKey.cj_skinDeiniterBlocks) as? [Any]
        if blocks == nil {
            blocks = Array()
            objc_setAssociatedObject(self, &CJSkinViewKey.cj_skinDeiniterBlocks, blocks, .OBJC_ASSOCIATION_RETAIN)
        }
        
        if let blocks = blocks {
            for er in blocks {
                if let er = er as? CJSkinDeiniter {
                    er.didSkinDeinit = block
                    return nil
                }
            }
        }
        let er = CJSkinDeiniter.init(didSkinDeinit: block)
        blocks?.append(er)
        return er
    }

    /// 切换主题通知实现
    @objc private func cj_skinChange() {
        let object = self
        
        if let cj_backroundColorkey = cj_backroundColorkey {
            object.backgroundColor = UIColor.cj_skinColor(cj_backroundColorkey)
        }
        if let cj_tintColorkey = cj_tintColorkey {
            object.tintColor = UIColor.cj_skinColor(cj_tintColorkey)
        }
        
        if let kit = object as? UILabel {
            if let cj_textColorkey = cj_textColorkey {
                kit.textColor = UIColor.cj_skinColor(cj_textColorkey)
            }
        }
        
        if let kit = object as? UITextField {
            if let cj_textColorkey = cj_textColorkey {
                kit.textColor = UIColor.cj_skinColor(cj_textColorkey)
            }
        }
        
        if let kit = object as? UITextView {
            if let cj_textColorkey = cj_textColorkey {
                kit.textColor = UIColor.cj_skinColor(cj_textColorkey)
            }
        }
        
        if let kit = object as? UIButton {
            if let cj_textColorkey = cj_textColorkey {
                kit.setTitleColor(UIColor.cj_skinColor(cj_textColorkey), for: .normal)
            }
        }
        
        // 回调
        cj_skinChangeAction()
    }
    
    /// 变化闭包回调
    private func cj_skinChangeAction() {
        if let cj_didSkin = cj_didSkin {
            cj_didSkin(self);
        }
    }
    
}


public extension UIColor {
    
    /// 根据key获取当前color
    class func cj_skinColor(_ key: String) -> UIColor {
        let sel = NSSelectorFromString(key)
        guard let colorClass = CJSkin.shared.colorClass else {
            return UIColor.black
        }
        let method = class_getClassMethod(colorClass, sel)
        guard let method = method else {
            return UIColor.black
        }
        let imp = method_getImplementation(method)
        typealias ImpType = @convention(c) (AnyClass?, Selector) -> CJSkinModel
        let exImp: ImpType = unsafeBitCast(imp, to: ImpType.self)
        let skinModel = exImp(colorClass, sel)
        let param = skinModel.param
        let color = cj_skinColor(param: param)
        return color
    }
    
    /// 根据param获取当前color
    class func cj_skinColor(param: [String: String]) -> UIColor {
        let currentSkin = CJSkin.shared.currentSkinKey
        let value = param[currentSkin]
        guard let value = value else { return UIColor.black }
        let color = UIColor.cj_color(value)
        return color
    }
}


extension UIImage {
    
    public static func cj_skinImage(_ name: String) -> UIImage? {
        var image: UIImage?
        if CJSkin.shared.skinImageEx == .xcassets {
            image = cj_skinXcassetsImage(name)
        } else if CJSkin.shared.skinImageEx == .bundle {
            image = cj_skinBundleImage(name)
        }
        image = UIImage(named: name)?.withRenderingMode(.alwaysOriginal)
        return image
    }
    
    /// 根据CJSkinImageEx.xcassets获取图片
    public static func cj_skinXcassetsImage(_ name: String) -> UIImage? {
        let suff = CJSkin.shared.currentSkinImageSuffixKey()
        var named = name
        if suff.count > 0 {
            named = name + suff
        } else {
            named = name + CJSkin.shared.currentSkinKey
        }
        let image = UIImage(named: named)?.withRenderingMode(.alwaysOriginal)
        return image
    }
    
    /// 根据CJSkinImageEx.bundle获取图片
    public static func cj_skinBundleImage(_ name: String) -> UIImage? {
        let bundleName = "\(CJSkin.shared.currentSkinKey).bundle"
        guard let path = Bundle.main.path(forResource: bundleName, ofType: nil),
              let bundle = Bundle(path: path) else {
            return nil
        }
        let image = UIImage(named: name, in: bundle, compatibleWith: nil)?.withRenderingMode(.alwaysOriginal)
        return image
    }
}



